import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

public class CoAuthorModel {
  Vector<Integer> degs_;
  int numCon_;

  int maxDeg_ = 0;
  int numNodes_;
  int cumDeg_;
  
  public static String getXPercentFileName(double x, int num_conn) {
    if (x == (int) x) {
      return String.format("x_%02d_%02d", (int) x, num_conn);
    } else {
      return String.format("x_0%.1f_%02d", x, num_conn);
    }
  }

  public static Vector<Integer> parseGraph(String fileName) throws IOException {
    Vector<Integer> degs = new Vector<Integer>();
    
    FileReader fr = new FileReader(fileName);
    BufferedReader in = new BufferedReader(fr);
    
    String line = in.readLine();
    String[] toks = line.split(" ");
    
    int numNonZero = Integer.parseInt(toks[0]) - Integer.parseInt(toks[1]);
    while (true) {
      line = in.readLine();
      
      if (line == null) {
        break;
      }
      
      line = line.replaceAll("[\\[\\]:]+", "");
      String[] ltoks = line.split("[ :\\[\\]]+");
      
      int deg = Integer.parseInt(ltoks[1]);
      
      if (deg == 0) break;
      
      degs.add(deg);
    }
    
    if (numNonZero != degs.size()) System.err.println("Number of non-zero degrees does not match.");
    
    return degs;
  }
  
  public void dumpGraph(String sourceDir, int date) throws IOException {
    FileWriter fw = new FileWriter(String.format("%s/%d.deg", sourceDir, date));
    PrintWriter out = new PrintWriter(fw);
    
    out.println(numNodes_ + " " + 0);
    
    for (int i = 0; i < degs_.size(); ++i) {
      out.println(String.format("[%d] %d", i+1, degs_.get(i)));
    }
    
    out.close();
    fw.close();
  }
  
  public static void dumpGraphGrowth(String sourceDir) throws IOException {
    FileWriter fw = new FileWriter(String.format("%s/growth", sourceDir));
    PrintWriter out = new PrintWriter(fw);

    int date = 19950101;
    
    while (date <= 20110101) {
      Vector<Integer> degs = null;
      
      degs = parseGraph(String.format("%s/%d.deg", sourceDir, date));
      out.println(degs.size() + " " + date);
      
      int d = date % 100;
      int m = (date / 100) % 100;
      int y = (date / 10000);
      
      m += 4;
      if (m > 12) {
        m %= 12;
        y++;
      }
      
      date = y * 10000 + m * 100 + d;
    }
    
    out.close();
    fw.close();
  }
  
  public static void generateBarabasi(String field) throws IOException {
    int[] numconn = {2, 5, 10};
    int total_nodes = field.equals("grqc") ? 14371 : 20106;
    
    for (int ic = 0; ic < numconn.length; ++ic) {
      int nc = numconn[ic];
      
      BarabasiModel bbm = new BarabasiModel("/home/sarfaraz/proj/gen/" + field + "/network/19950101.deg", nc);
      bbm.run("/home/sarfaraz/proj/gen/" + field, total_nodes);
    }  
  }
  
  public static void generateXPercent(String field) throws IOException {
    double[] xvalues = { 0.5, 0.2 };
    int[] numconn = { 5 };
    int total_nodes = field.equals("grqc") ? 14371 : 20106;
    
    
    for(int ix = 0; ix < xvalues.length; ++ix) {
      double x = xvalues[ix];  
      
      for (int ic = 0; ic < numconn.length; ++ic) {
        int nc = numconn[ic];

        XPercentModel xpm = new XPercentModel("/home/sarfaraz/proj/gen/" + field + "/network/19950101.deg", x, nc);
        xpm.run("/home/sarfaraz/proj/gen/" + field, total_nodes);
      }
    }  
  }
  
  public static void dumpComparison(String dir1, String dir2, String output) throws IOException {
    int date = 19950501;
    
    FileWriter fw = new FileWriter(output);
    PrintWriter out = new PrintWriter(fw);

    while (date <= 20110101) {
      Vector<Integer> degs1 = parseGraph(String.format("%s/%d.deg", dir1, date));
      Network n1 = new Network(degs1);
      
      Vector<Integer> degs2 = parseGraph(String.format("%s/%d.deg", dir2, date));
      Network n2 = new Network(degs2);
      
      Network.Similarity sm = Network.calculateSim1(n1, n2);
      
      out.println(String.format("%d : %f %f", date, sm.maxDiff, sm.avgDiff));

      int d = date % 100;
      int m = (date / 100) % 100;
      int y = (date / 10000);
      
      m += 4;
      if (m > 12) {
        m %= 12;
        y++;
      }
      
      date = y * 10000 + m * 100 + d;
    }
    
    out.close();
    fw.close();
  }
  
  public static void dumpPercentileComparison(String dir1, String dir2, String output) throws IOException {
    int date = 19950501;
    
    FileWriter fw = new FileWriter(output);
    PrintWriter out = new PrintWriter(fw);

    while (date <= 20110101) {
      Vector<Integer> degs1 = parseGraph(String.format("%s/%d.deg", dir1, date));
      Network n1 = new Network(degs1);

      Vector<Integer> degs2 = parseGraph(String.format("%s/%d.deg", dir2, date));
      Network n2 = new Network(degs2);

      Network.Similarity sm = Network.calculateSim2(n1, n2);

      out.println(String.format("%d : %f %f", date, sm.maxDiff, sm.avgDiff));

      int d = date % 100;
      int m = (date / 100) % 100;
      int y = (date / 10000);
      
      m += 4;
      if (m > 12) {
        m %= 12;
        y++;
      }
      
      date = y * 10000 + m * 100 + d;
    }
    
    out.close();
    fw.close();    
  }
  
  public static void main(String[] args) {
    CoAuthorModel com = new CoAuthorModel();
    
    try {
      String field = "hepth";

      String d1 = String.format("/home/sarfaraz/proj/gen/%s/network", field);
      String d2 = null;
      String out = null;

//      dumpGraphGrowth(d1);

//      generateBarabasi(field);
      generateXPercent(field);

      double[] xvalues = { 0.5, 0.2 };
      int[] numconn = { 5 };      

      for (int ic = 0; ic < numconn.length; ++ic) {
        int nc = numconn[ic];

        // Barabasi.
        d2 = String.format("/home/sarfaraz/proj/gen/%s/b_%d", field, nc);
        out = String.format("/home/sarfaraz/proj/gen/%s/b%d.stat", field, nc);
//        dumpComparison(d1, d2, out);
//        dumpPercentileComparison(d1, d2, out + "2");

        for (int ix = 0; ix < xvalues.length; ++ix) {
          double x = xvalues[ix];

          d2 = "/home/sarfaraz/proj/gen/" + field + "/" + getXPercentFileName(x, nc);
          out = String.format("/home/sarfaraz/proj/gen/%s/%s.stat", field, getXPercentFileName(x, nc));

          // XPercent
          dumpComparison(d1, d2, out);
          try {
            dumpPercentileComparison(d1, d2, out + "2");
          } catch (IOException ie) {
            System.err.println(ie.getMessage());
          }
        }
      }
      
      field = "grqc";

      d1 = String.format("/home/sarfaraz/proj/gen/%s/network", field);
      d2 = null;
      out = null;

//      dumpGraphGrowth(d1);

//      generateBarabasi(field);
      generateXPercent(field);

//      double[] xvalues = { 1, 2, 5, 10 };
//      int[] numconn = { 2 , 5, 10 };      

      for (int ic = 0; ic < numconn.length; ++ic) {
        int nc = numconn[ic];

        // Barabasi.
        d2 = String.format("/home/sarfaraz/proj/gen/%s/b_%d", field, nc);
        out = String.format("/home/sarfaraz/proj/gen/%s/b%d.stat", field, nc);
//        dumpComparison(d1, d2, out);
//        dumpPercentileComparison(d1, d2, out + "2");

        for (int ix = 0; ix < xvalues.length; ++ix) {
          double x = xvalues[ix];

          d2 = "/home/sarfaraz/proj/gen/" + field + "/" + getXPercentFileName(x, nc);
          out = String.format("/home/sarfaraz/proj/gen/%s/%s.stat", field, getXPercentFileName(x, nc));

          // XPercent
          dumpComparison(d1, d2, out);
          try {
            dumpPercentileComparison(d1, d2, out + "2");
          } catch (IOException ie) {
            System.err.println(ie.getMessage());
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
}
